﻿using BusinessLogic;
using BusinessLogic.Interfaces;
using DataAccess;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using MyPetHub.Common;
using MyPetHub.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Dynamic;
using System.Linq;
using System.Linq.Expressions;

namespace MyPetHub.Controllers
{
    public partial class HomeController : BaseController
    {
        private readonly ILogger<HomeController> _logger;//_logger.LogInformation("打印日志");

        Expression<Func<PetInfo, dynamic>> petInfoFunc;
        int perPageCount = 20;
        int readRankCount = 10;
        int perBatchCount = 10;
        int accessCountHeap = 10;

        public HomeController(ILogger<HomeController> logger, MyPetHubContext dbContext, IMemoryCache mcObj, IHttpContextAccessor httpContextAccessor, IConfiguration configuration)
            :base(mcObj, dbContext, httpContextAccessor)
        {
            _logger = logger;

            //生成宠物信息表达式
            petInfoFunc = (x) => new {
                src = $"/file/{subDomain}/imgs/" + x.coverimgsrc,
                navurl = "/Home/PetInfo?id=" + x.petinfoid,
                nickname = x.nickname,
                breed = x.breed,
                sterstatus = x.sterstatus,
                vaccinstatus = x.vaccinstatus,
                id= x.petinfoid,
                price = x.price,
            };

            perPageCount = configuration.GetValue<int>("PerPageCount");//宠物信息每页数据量
            readRankCount = configuration.GetValue<int>("ReadRankCount");//养宠知识阅读排名显示数量
            perBatchCount = configuration.GetValue<int>("perBatchCount");//部分页每批次获取的数据量
            accessCountHeap = configuration.GetValue<int>("AccessCountHeap");//访问累积量，超过该设置后更新统计表
        }

        //首页
        public async Task<IActionResult> Index()
        {
            //首页广告图片地址
            await GetBannerAdvertInfo();
            await GetBlockAdvertInfo();

            //推荐宠物故事
            var petStorys = await dbContext.PetStory.Where(x => x.isrecommended == true).OrderBy(x => x.updatetime).Take(10).ToListAsync();

            //走马灯故事
            var bestStorys = petStorys.Take(3).Select(x=>new { src = "/file/super/imgs/"+ x.coverimgsrc, navurl = "/Home/PetStoryContent?id=" + x.id, title=x.title}).ToList();
            ViewData["petStoryCarousel"] = JsonConvert.SerializeObject(bestStorys, formatSettings);

            //推荐故事
            var recommendStorys = petStorys.Skip(3).Take(7).Select(x => new { title = x.title, navurl = "/Home/PetStoryContent?id=" + x.id }).ToList();
            ViewData["recommendStory"] = JsonConvert.SerializeObject(recommendStorys, formatSettings);

            //宠物信息
            int petInfoCount = await dbContext.PetInfo.Where(x => x.merchantid == merID).CountAsync();
            ViewData["petInfoCount"] = petInfoCount;
            ViewData["pageSize"] = perPageCount;

            var petInfo = dbContext.PetInfo.Where(x => x.merchantid == merID).OrderBy(x => x.updatetime).Take(perPageCount).Select(petInfoFunc).ToList();
            ViewData["petInfo"] = JsonConvert.SerializeObject(petInfo, formatSettings);

            //统计访问次数
            await StatisticsAccessCount();

            //部分页每批次获取数据量
            ViewData["perBatchCount"] = perBatchCount;

            return View();
        }

        //获取横幅广告信息
        private async Task GetBannerAdvertInfo()
        {
            AdvertInfo? advInfo = await dbContext.AdvertInfo.Where(x => x.isshow == true && x.isblock == false).FirstOrDefaultAsync();
            if (advInfo != null && advInfo.enddate.Date >= DateTime.Now.Date)
            {
                ViewData["bannerAdvertImg"] = "/file/super/adverts/" + advInfo.imgsrc;
                ViewData["bannerAdvertUrl"] = advInfo.adverturl;
                ViewData["bannerAdvertID"] = advInfo.id;
            }
            else
            {
                ViewData["bannerAdvertImg"] = "/advert.jpg";
                ViewData["bannerAdvertUrl"] = "#";
                ViewData["bannerAdvertID"] = "-1";
            }
        }

        //获取块状广告信息
        private async Task GetBlockAdvertInfo()
        {
            AdvertInfo? advInfo = await dbContext.AdvertInfo.Where(x => x.isshow == true && x.isblock == true).FirstOrDefaultAsync();
            if (advInfo != null && advInfo.enddate.Date >= DateTime.Now.Date)
            {
                ViewData["blockAdvertImg"] = "/file/super/adverts/" + advInfo.imgsrc;
                ViewData["blockAdvertUrl"] = advInfo.adverturl;
                ViewData["blockAdvertID"] = advInfo.id;
            }
            else
            {
                ViewData["blockAdvertImg"] = "/advert_block.jpg";
                ViewData["blockAdvertUrl"] = "#";
                ViewData["blockAdvertID"] = "-1";
            }
        }

        //首页访问人次统计
        private async Task StatisticsAccessCount()
        {
            if (HttpContext.Session.GetString("firstPage") == null)
            {
                HttpContext.Session.SetString("firstPage", "0");
                ReadCountHeap? rchObj = await dbContext.ReadCountHeap.Where(x =>x.merchantid == -1 && x.id == -1).FirstOrDefaultAsync();
                if (rchObj != null)
                {
                    rchObj.readcount += 1;
                    if (rchObj.readcount >= accessCountHeap)
                    {
                        var statObj = await dbContext.StatisticsInfo.Where(x => x.id == 1).FirstOrDefaultAsync();
                        statObj.readcount += rchObj.readcount;

                        rchObj.readcount = 0;
                    }
                }
                else
                {
                    ReadCountHeap newRchObj = new ReadCountHeap();
                    newRchObj.merchantid = -1;
                    newRchObj.id = -1;
                    newRchObj.readcount = 1;
                    await dbContext.ReadCountHeap.AddAsync(newRchObj);
                }

                await dbContext.SaveChangesAsync();
            }
        }

        //宠物信息分页
        [HttpPost]
        public async Task<JsonResult> GetPaginationInfo([FromBody] object json)
        {
            JObject jobj = JObject.Parse(json.ToString());
            int pageNum = int.Parse(jobj["pageNum"].ToString());
            string breedName = jobj["breedName"].ToString();
            int specialsNum = int.Parse(jobj["specialsNum"].ToString());

            PaginationData<List<dynamic>> paginationData = new PaginationData<List<dynamic>>();
            int dataCount = 0;
            List<dynamic> petInfo;
            if (specialsNum == 0)//全部种类
            {
                if(string.IsNullOrEmpty(breedName))//无搜索条件
                {
                    dataCount = await dbContext.PetInfo.Where(x => x.merchantid == merID).CountAsync();
                    petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID).OrderBy(x => x.updatetime).Skip((pageNum - 1) * perPageCount).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                }
                else
                {
                    dataCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.breed.Contains(breedName)).CountAsync();
                    petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.breed.Contains(breedName)).OrderBy(x => x.updatetime)
                        .Skip((pageNum - 1) * perPageCount).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                }
            }
            else
            {
                if (string.IsNullOrEmpty(breedName))//无搜索条件
                {
                    dataCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum).CountAsync();
                    petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum).OrderBy(x => x.updatetime)
                        .Skip((pageNum - 1) * perPageCount).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                }
                else
                {
                    dataCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum && x.breed.Contains(breedName)).CountAsync();
                    petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum && x.breed.Contains(breedName)).OrderBy(x => x.updatetime)
                        .Skip((pageNum - 1) * perPageCount).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                }
            }

            paginationData.data = petInfo;
            paginationData.dataCount = dataCount;

            return new JsonResult(paginationData);
        }

        //根据种类筛选
        [HttpPost]
        public async Task<JsonResult> ScreenSpecials([FromBody] object json)
        {
            JObject jobj = JObject.Parse(json.ToString());
            int specialsNum = int.Parse(jobj["specialsNum"].ToString());

            PaginationData<List<dynamic>> paginationData = new PaginationData<List<dynamic>>();
            if (specialsNum == 0)//全部种类
            {
                int petInfoCount = await dbContext.PetInfo.Where(x => x.merchantid == merID).CountAsync();
                var petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID).OrderBy(x => x.updatetime).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                paginationData.data = petInfo;
                paginationData.dataCount = petInfoCount;
            }
            else
            {
                int petInfoCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum).CountAsync();
                var petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum).OrderBy(x => x.updatetime).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                paginationData.data = petInfo;
                paginationData.dataCount = petInfoCount;
            }

            return new JsonResult(paginationData);
        }

        //品种搜索
        [HttpPost]
        public async Task<JsonResult> SearchBreed([FromBody] object json)
        {
            JObject jobj = JObject.Parse(json.ToString());
            string breedName = jobj["breedName"].ToString();
            int specialsNum = int.Parse(jobj["specialsNum"].ToString());

            PaginationData<List<dynamic>> paginationData = new PaginationData<List<dynamic>>();
            if (specialsNum == 0)//全部种类
            {
                int petInfoCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.breed.Contains(breedName)).CountAsync();
                var petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.breed.Contains(breedName)).OrderBy(x => x.updatetime).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                paginationData.data = petInfo;
                paginationData.dataCount = petInfoCount;
            }
            else
            {
                int petInfoCount = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum && x.breed.Contains(breedName)).CountAsync();
                var petInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.speciesid == specialsNum && x.breed.Contains(breedName)).OrderBy(x => x.updatetime).Take(perPageCount).Select(petInfoFunc).ToListAsync();
                paginationData.data = petInfo;
                paginationData.dataCount = petInfoCount;
            }

            return new JsonResult(paginationData);
        }

        //宠物信息
        public async Task<IActionResult> PetInfo()
        {
            long pefInfoID = long.Parse(Request.Query["id"].ToString());

            await GetBlockAdvertInfo();

            ViewData["subDomain"] = subDomain;
            PetInfo? piObj = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.petinfoid == pefInfoID).FirstOrDefaultAsync();
            if(piObj == null)
            {
                throw new Exception("数据不存在" + pefInfoID);
            }

            await LogPetInfoAccessCount(pefInfoID);

            var otherPetInfo = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.breed == piObj.breed).Take(5).Select(petInfoFunc).ToListAsync();
            var petInfoForJson = otherPetInfo.Where(x=>x.id != pefInfoID).ToList();

            if (petInfoForJson.Count > 0)
                ViewData["otherPetInfo"] = JsonConvert.SerializeObject(petInfoForJson, formatSettings);
            else
                ViewData["otherPetInfo"] = "[]";

            return View(piObj);
        }

        //记录养宠知识访问次数
        public async Task LogPetInfoAccessCount(long dataID)
        {
            ReadCountHeap? rchObj = await dbContext.ReadCountHeap.Where(x => x.merchantid == merID && x.id == dataID).FirstOrDefaultAsync();
            if (rchObj != null)
            {
                rchObj.readcount += 1;
                if (rchObj.readcount >= accessCountHeap)
                {
                    var statObj = await dbContext.StatisticsInfo.Where(x => x.id == 5).FirstOrDefaultAsync();
                    statObj.readcount += rchObj.readcount;

                    //var piObj = await dbContext.PetInfo.Where(x => x.merchantid == merID && x.petinfoid == dataID).FirstOrDefaultAsync();

                    rchObj.readcount = 0;
                }
            }
            else
            {
                ReadCountHeap newRchObj = new ReadCountHeap();
                newRchObj.merchantid = merID;
                newRchObj.id = dataID;
                newRchObj.readcount = 1;
                await dbContext.ReadCountHeap.AddAsync(newRchObj);
            }

            await dbContext.SaveChangesAsync();
        }

        //养宠知识批次获取
        [HttpPost]
        public async Task<IActionResult> RaisingPetKnowledge_Partial([FromBody] object json)
        {
            JObject jobj = JObject.Parse(json.ToString());
            long lastRecommandKnowledgeID = long.Parse(jobj["lastRecommandKnowledgeID"].ToString());

            List<PetKnowledge> pkList = await dbContext.PetKnowledge.OrderBy(x => x.id).Where(x => x.isrecommended == true && x.id > lastRecommandKnowledgeID).Take(perBatchCount).ToListAsync();

            List<RaisingPetKnowledgeModel> rpkmList = new List<RaisingPetKnowledgeModel>();
            foreach (PetKnowledge item in pkList)
            {
                RaisingPetKnowledgeModel obj = new RaisingPetKnowledgeModel();
                obj.id = item.id;
                obj.imgurl = item.coverimgsrc;
                obj.title = item.title;
                obj.subtitle = item.subtitle;
                obj.species = speciesinfoDict[item.speciesid ?? 1];
                rpkmList.Add(obj);
            }

            return View(rpkmList);
        }

        //广告点击
        [HttpPost]
        public async Task<JsonResult> AdvertClick([FromBody] object json)
        {
            JObject jobj = JObject.Parse(json.ToString());
            long advertID =long.Parse( jobj["advertID"].ToString());
            if (advertID == -1)
                return new JsonResult("ok");

            if (HttpContext.Session.GetString("advert") == null)
            {
                HttpContext.Session.SetString("advert", "0");

                var advertObj = await dbContext.AdvertInfo.Where(x => x.id == advertID).FirstOrDefaultAsync();
                advertObj.readcount += 1;

                await dbContext.SaveChangesAsync();
            }

            return new JsonResult("ok");
        }

        //宠物寄养
        public async Task<IActionResult> PetFosterage()
        {
            PetFosterage? pfObj = await dbContext.PetFosterage.Where(x => x.merchantid == merID && x.datatype == 0).FirstOrDefaultAsync();
            if(pfObj == null)
            {
                pfObj = new PetFosterage();
                pfObj.content = "暂无公告信息";
            }

            await GetBannerAdvertInfo();

            ViewData["subDomain"] = subDomain;
            return View(pfObj);
        }

        //宠物美容
        public async Task<IActionResult> PetBeauty()
        {
            PetFosterage? pfObj = await dbContext.PetFosterage.Where(x => x.merchantid == merID && x.datatype == 1).FirstOrDefaultAsync();
            if (pfObj == null)
            {
                pfObj = new PetFosterage();
                pfObj.content = "暂无公告信息";
            }

            await GetBannerAdvertInfo();

            ViewData["subDomain"] = subDomain;
            return View(pfObj);
        }

        //联系我们
        public async Task<IActionResult> AboutUS()
        {
            AboutUS? pfObj = await dbContext.AboutUS.Where(x => x.merchantid == merID).FirstOrDefaultAsync();
            if (pfObj == null)
            {
                pfObj = new AboutUS();
                pfObj.introduce = "暂无联系信息";
            }

            await GetBannerAdvertInfo();

            ViewData["subDomain"] = subDomain;
            return View(pfObj);
        }
    }
}